<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <button>按钮</button>
  <input type="text">
  <button class="cancel">取消</button>

  <script>
    function hydebounce(fn, delay, immediate = false, resultCallback) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
      let isInvoke = false

      // 2.触发事件时执行的函数
      const _debounce = function (...args) {
        // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
        if (timer) clearTimeout(timer)

        // 第一次操作不需要延迟
        let res = undefined
        if (immediate && !isInvoke) {
          res = fn.apply(this, args)
          if (resultCallback) resultCallback(res)
          isInvoke = true
          return
        }

        // 2.2.延迟去执行对应的fn函数(传入的回调函数)
        timer = setTimeout(() => {
          res = fn.apply(this, args)
          if (resultCallback) resultCallback(res)
          timer = null // 执行过函数之后, 将timer重新置null
          isInvoke = false
        }, delay);
      }

      // 3.给_debounce绑定一个取消的函数
      _debounce.cancel = function () {
        if (timer) clearTimeout(timer)
      }

      // 返回一个新的函数
      return _debounce
    }

    function hydebounce1(fn, delay, immediate = false, resultCallback) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
      let isInvoke = false

      // 2.触发事件时执行的函数
      const _debounce = function (...args) {
        return new Promise((resolve, reject) => {
          try {
            if (timer) clearTimeout(timer)
            let res = undefined
            if (immediate && !isInvoke) {
              res = fn.apply(this, args)
              resolve(res)
              isInvoke = true
              return
            }
            timer = setTimeout(() => {
              res = fn.apply(this, args)
              resolve(res)
              timer = null
              isInvoke = false
            }, delay);
          } catch (err) {
            reject(err)
          }
        })
      }

      // 3.给_debounce绑定一个取消的函数
      _debounce.cancel = function () {
        if (timer) clearTimeout(timer)
      }

      // 返回一个新的函数
      return _debounce
    }
  </script>

  <script>
    // 1.获取input元素
    const inputEl = document.querySelector("input")
    const cancelBtn = document.querySelector(".cancel")

    // 3.自己实现的防抖
    let counter = 1
    const debounceFn = hydebounce(function (event) {
      console.log(`发送网络请求${counter++}:`, this, event)
    }, 5000, true)
    // inputEl.oninput = debounceFn
    const myDebounceFn = hydebounce(function (name, age, height) {
      console.log('-----', name, age, height)
      return 'coderwhy 哈哈哈'
    }, 1000, false, function (res) {
      console.log('执行后的结果:', res)
    })
    const res = myDebounceFn('why', 18, 1.88)

    const myDebounceFn1 = hydebounce1(function (name, age, height) {
      console.log('-----', name, age, height)
      return 'coderwhy 哈哈哈'
    }, 1000, false)
    myDebounceFn1('why', 18, 1.88).then(res => {
      console.log(res)
    })


    // 4.实现取消的功能
    cancelBtn.onclick = function () {
      debounceFn.cancel()
    }

  </script>

</body>

</html>